﻿/*
 * Created by SharpDevelop.
 * User: Administrator
 * Date: 3/1/2011
 * Time: 8:30 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using TomatoSynchronizer.Entities;
using TomatoSynchronizer.Store;
using HtmlAgilityPack;

namespace TomatoSynchronizer.Synchronizer
{
	/// <summary>
	/// Description of DeviseSynchronizer
	/// </summary>
	public static class DeviseSynchronizer
	{
		public static void Synchronize(Site siteSrc,Site siteDest,HtmlWeb client,SyncDirection direction)
		{
			switch(direction)
			{
				case SyncDirection.Download:
					UpLoadItems(siteDest,siteSrc,client,direction);
					break;
				case SyncDirection.Upload:
					UpLoadItems(siteSrc,siteDest,client,direction);
					break;
				case SyncDirection.DownloadAndUpload:
					UpLoadItems(siteDest,siteSrc,client,SyncDirection.Download);
					UpLoadItems(siteSrc,siteDest,client,SyncDirection.Upload);
					break;
				case SyncDirection.UploadAndDownload:
					UpLoadItems(siteSrc,siteDest,client,SyncDirection.Upload);
					UpLoadItems(siteDest,siteSrc,client,SyncDirection.Download);
					break;
				case SyncDirection.Synchronize:
					DeviseStore DeviseStoreDest = new DeviseStore(siteDest,client);
					DeviseStoreDest.Truncate();
					
					UpLoadItems(siteSrc,siteDest,client,SyncDirection.Upload);
					
					DeviseStoreDest.DeleteDummy();
					break;
			}
		}
		
		private static void UpLoadItems(Site _siteSrc,Site _siteDest,HtmlWeb client,SyncDirection direction)
		{
			DeviseStore DeviseStoreSrc = new DeviseStore(_siteSrc,client);
			DeviseStore DeviseStoreDest = new DeviseStore(_siteDest,client);
			
			Devise[] DevisesSrc =  DeviseStoreSrc.LoadItems();
			Devise[] DevisesDest =  DeviseStoreDest.LoadItems();
			
			MappingStore mappingStoreSrc = new MappingStore(_siteSrc,_siteDest,"Devises_id");
			MappingStore mappingStoreDest = new MappingStore(_siteDest,_siteSrc,"Devises_id");
			
			mappingStoreSrc.Clean<Devise>(DeviseStoreSrc,DeviseStoreDest);
			mappingStoreDest.Clean<Devise>(DeviseStoreDest,DeviseStoreSrc);
			
			foreach(Devise DeviseSrc in DevisesSrc)
			{
				if(DeviseSrc.code != "XYZ")
				{
					//we assume the Devise is not yet synchronized
					bool synchronized = false;
					
					//we check if a mapping already exists for this Devise in the destination store
					foreach(Mapping mapping in mappingStoreSrc.Mappings)
					{
						if(!synchronized)
						{
							if(mapping.SrcValue == DeviseSrc.id)
							{
								if(!string.IsNullOrEmpty(mapping.DestValue))
								{
									//this Devise already exists in the destination store
									//we check if everything changed since the last synchronization
									Devise DeviseDest = DeviseStoreDest.GetItem(mapping.DestValue);
									if(DeviseDest.id != null)
									{
										synchronized = SynchronizeItem(DeviseSrc,DeviseDest,direction,mappingStoreSrc);
									}
									else
									{
										//the mapping exists, but the Devise has been deleted in the destination store
										//we set a flag that this mapping does not exists anymore
										mapping.Exists = false;
									}
								}
							}							
						}
					}
					
					if(!synchronized)
					{
						//there is no mapping, we check if this Devise already exists in the destination store
						foreach(Devise DeviseDest in DevisesDest)
						{
							if(DeviseSrc.code == DeviseDest.code)
							{
								//we get the 2 currencies from sites to get sure they really exist
								Devise src = DeviseSrc.Store.GetItem(DeviseSrc.id);
								Devise dest = DeviseDest.Store.GetItem(DeviseDest.id);
								
								if(src != null)
								{
									if(dest != null)
									{
										Mapping mapping = new Mapping(DeviseSrc.id,DeviseDest.id,"Devises_id");
										mappingStoreSrc.Mappings.Add(mapping);
										
										synchronized = SynchronizeItem(DeviseSrc,DeviseDest,direction,mappingStoreSrc);
									}
									else
									{
										synchronized = false;
									}
								}
								else
								{
									synchronized = true;
								}
							}
						}
					}
					
					if(!synchronized)
					{
						//no mapping the Devise is new
						//we insert it in the destination store
						string remoteId = string.Empty;
						
						remoteId = DeviseStoreDest.InsertItem(DeviseSrc);
						
						synchronized = remoteId != string.Empty;
						
//						synchronized = true;
						
						if(!synchronized)
						{
							throw new Exception("The Devise " + DeviseSrc.title + " has not been synchronized");
						}
						
						Mapping mapping = new Mapping(DeviseSrc.id,remoteId,"Devises_id");
						mappingStoreSrc.Mappings.Add(mapping);
						synchronized = true;
					}
					
					if(!synchronized)
					{
						throw new Exception("could not synchronize the Devise " + DeviseSrc.title);
					}										
				}
				
				DeviseStoreSrc.PersistItem(DeviseSrc);
			}
			
			mappingStoreSrc.Save();
			
			mappingStoreDest.Truncate();
			
			//we save the mappings in the destination MappingStore too
			foreach(Mapping mapping in mappingStoreSrc.Mappings)
			{
				if(mapping.Exists)
				{
					Mapping mappingDest = new Mapping(mapping.DestValue,mapping.SrcValue,mapping.Property);
					mappingStoreDest.Mappings.Add(mappingDest);
				}
			}
			
			mappingStoreDest.Save();
			
			//we check if the 2 MappingStore are synchronized
			if(mappingStoreSrc.Mappings.Count != mappingStoreDest.Mappings.Count)
			{
				throw new Exception("The mapping store are not synchronized");
			}
		}
		
		private static bool SynchronizeItem(Devise DeviseSrc,Devise DeviseDest,SyncDirection direction,MappingStore mappingStore)
		{
			bool synchronized = true;
			
			if(!DeviseSrc.Equals(DeviseDest))
			{
				synchronized = false;
				
				//we update the destination Devise
				DeviseSrc.id = DeviseDest.id;
				
				synchronized = DeviseDest.Store.UpdateItem(DeviseSrc);
			}
			
			return synchronized;
		}
		
		private static string UploadItem(DeviseStore DeviseStoreDest,Devise Devise)
		{
			string remoteId = string.Empty;
			
			remoteId = DeviseStoreDest.InsertItem(Devise);
			
			return remoteId;
		}
	}
}
